package application.mvc.biz.group;

import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import com.jfinal.ext.kit.DateKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import application.common.model.Board;
import application.common.model.Cabinet;
import application.common.model.FaultBox;
import application.common.model.Store;
import application.common.model.StoreBox;
import application.common.model.StoreBoxLog;
import application.common.model.StoreLog;
import application.common.plugins.serialPort.SerialCommunication;
import application.common.render.Cmd;
import application.common.ui.ProgressStage;
import application.common.util.CmdUtil;
import application.common.util.Convert;
import application.common.util.ExtDbUtil;
import application.common.util.LayerUtil;
import application.common.util.RouteUtil;
import application.common.util.ShiroUtil;
import application.common.util.UuidUtil;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.util.Duration;

public class CabGroupController implements Initializable{
	
	private final Log log = Log.getLog(getClass());

	private CabGroupController controller;
    public StringProperty storeId = new SimpleStringProperty();
    public BooleanProperty open = new SimpleBooleanProperty();
    
	@FXML
	private Label headerLabel;
	
	@FXML
	private Label copyrightLabel;
	
	@FXML
	private ImageView portraitImageView;
	
	@FXML
	private Label usernameLabel;
	
	@FXML
	private Label roleNameLabel;
    
	@FXML
	private Label navLabel;
    
	@FXML
	private Pane cabinetListPane;
	
	@FXML
	private Pane timerOutLinePane;

	@FXML
	private Pane timerInLinePane;

	@FXML
	private Label timerLabel;
	private Timeline animation;
	private RotateTransition rotateTransitionOut;
	private RotateTransition rotateTransitionIn;
	
	private ObservableList<CabinetPanel> dataList = FXCollections.observableArrayList();

	private boolean isDestroy;
	
	public CabGroupController(String storeId,boolean open) {
		this.controller=this;
		this.storeId.set(storeId);
		this.open.set(open);
	}

	public void initialize(URL arg0, ResourceBundle arg1) {
		headerLabel.setText(ShiroUtil.getSoftName());
		copyrightLabel.setText(ShiroUtil.getCopyright());
		portraitImageView.setImage(ShiroUtil.getUser().getPortrait());
		usernameLabel.setText(ShiroUtil.getUser().getName());
		roleNameLabel.setText(ShiroUtil.getUser().getRoleName());
		
		if(open.get()) navLabel.setText("卷宗提取"); else navLabel.setText("选择存储柜子");
		ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
			@Override
			protected Void call() throws Exception {
		    	String _sql="select * from "+Cabinet.TABLE_NAME +" where 1=1  ";
		    	if(open.get()) {
		    		_sql+=" and id in (select distinct cabinetId from "+StoreBox.TABLE_NAME+" where storeId='"+storeId.get()+"' )";
		    	}
		    	_sql+=" order by sort asc ";
				List<Cabinet> cabinets=Cabinet.dao.find(_sql);
				CabinetPanel cabinetPanel;
				CabResult cabResult;
				for (Cabinet cabinet:cabinets) {
					if(!open.get()) {
						cabinet.setBoards(Board.dao.find("SELECT * FROM "+Board.TABLE_NAME+" WHERE cabinetId=? ",cabinet.getId()));
					}
					cabinetPanel=new CabinetPanel(controller,cabinet);
					dataList.add(cabinetPanel);
					if(open.get()) {
						cabResult=cabinetPanel.doOpen();
						if(!cabResult.isCode()) {
							log.debug(cabResult.getMessage());
						}
					}
				}
				Platform.runLater(new Runnable() {
				    public void run() {
				    	cabinetListPane.getChildren().addAll(dataList);
				    }
				});
				if(!isDestroy) {
					rotateTransitionOut = new RotateTransition(Duration.seconds(10), timerOutLinePane);
					rotateTransitionOut.setFromAngle(0);
					rotateTransitionOut.setToAngle(360);
					rotateTransitionOut.setByAngle(360); // 设置旋转的角度
					rotateTransitionOut.setCycleCount(Animation.INDEFINITE); // 设置旋转次数，我们需要旋转无数次
					rotateTransitionOut.setInterpolator(Interpolator.LINEAR);
					rotateTransitionOut.play();

					rotateTransitionIn = new RotateTransition(Duration.seconds(10), timerInLinePane);
					rotateTransitionIn.setFromAngle(360);
					rotateTransitionIn.setToAngle(0);
					rotateTransitionIn.setByAngle(360); // 设置旋转的角度
					rotateTransitionIn.setCycleCount(Animation.INDEFINITE); // 设置旋转次数，我们需要旋转无数次
					rotateTransitionIn.setInterpolator(Interpolator.LINEAR);
					rotateTransitionIn.play();
					startCountDown();
				}
				return null;
			}
		}, open.get()?"开柜中...":"查询存储柜中...").show();
	}
	
	public void exit(ActionEvent event) {
		if(!isDestroy) {
			isDestroy=true;
			if(open.get()) {
				ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
					@Override
					protected Void call() throws Exception {
						log.info(String.format("卷宗【%s】提取日志记录！", storeId.get()));
						try {
							ExtDbUtil.beginTran();
							List<CabResult> cabResults=new LinkedList<CabResult>();
							CabResult cabResult;
							for(CabinetPanel cabinetPanel:dataList) {
								if(cabinetPanel.isOpen()) {
									cabResult=cabinetPanel.doSave();
									cabResults.add(cabResult);
								}
							}
							
							for(CabResult result:cabResults) {
								if(!result.isCode()) {
									throw new Exception(result.getMessage());
								}
							}
							for(CabResult result:cabResults) {
								if(!result.getStoreLog().save()) {
									throw new Exception("日志记录异常！");
								}
								
								for(String storeBoxId:result.getRemoveBoxs()) {
									if(!StoreBox.dao.deleteById(storeBoxId)) {
										throw new Exception("移除存放柜子记录异常！");
									}
								}
								
								for(StoreBoxLog storeBoxLog:result.getStoreBoxLogs()) {
									if(!storeBoxLog.save()) {
										throw new Exception("记录移除存放柜子日志异常！");
									}
								}
							}
							
							double storeTotal=Db.queryDouble("select count(id) from "+StoreBox.TABLE_NAME+" where storeId=?",storeId.get());
							if(storeTotal==0) {
								log.info(String.format("卷宗【%s】已被全部取走，开始移出存储信息！", storeId.get()));
								if(!Store.dao.deleteById(storeId.get())) {
									throw new Exception(String.format("卷宗【%s】已被全部取走，移出存储信息异常，请核实！", storeId.get()));
								}
								log.info(String.format("卷宗【%s】已被全部取走，移出存储信息成功！", storeId.get()));
							}
							ExtDbUtil.commit();
							destroy();
							RouteUtil.goArchives();
						}catch (Exception e) {
							log.error("提取卷宗退出异常",e);
							try {
								ExtDbUtil.rollback();
							} catch (SQLException e1) {
								log.error("事务回滚异常",e1);
							}
							Platform.runLater(new Runnable() {
							    public void run() {
							    	isDestroy=false;
							    	LayerUtil.open(e.getMessage(), 500);
							    }
							});
						}
						return null;
					}
				},"保存记录中...").show();
			}else {
				ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
					@Override
					protected Void call() throws Exception {
						destroy();
						RouteUtil.goArchives();
						return null;
					}
				},"返回卷宗列表中...").show();
			}
		}
	}
	
	public void startCountDown() {
		animation = new Timeline(new KeyFrame(Duration.millis(1000), new EventHandler<ActionEvent>() {
			public void handle(ActionEvent event) {
				if(RouteUtil.getTime()>0) {
					RouteUtil.setTime(RouteUtil.getTime() - 1);
					if (RouteUtil.getTime() == 0) {
						timerLabel.setText("0");
						LayerUtil.open("操作超时！", 999);
					} else if (RouteUtil.getTime() > 0) {
						timerLabel.setText(RouteUtil.getTime() + "");
					}
				}
			}
		}));
		animation.setCycleCount(Timeline.INDEFINITE);
		animation.play();
	}

	public void destroy() {
		if (animation != null) {
			animation.stop();
		}
		if (rotateTransitionOut != null) {
			rotateTransitionOut.stop();
		}
		if (rotateTransitionIn != null) {
			rotateTransitionIn.stop();
		}
		if(open.get()) {
			for(CabinetPanel cabinetPanel:dataList) {
				if(cabinetPanel.isOpen()) {
					cabinetPanel.close();
				}
			}
		}
	}

	public boolean isDestroy() {
		return isDestroy;
	}

	public void setDestroy(boolean isDestroy) {
		this.isDestroy = isDestroy;
	}
	
	
}

/**
 * 柜子组
 * @author love
 *
 */
class CabinetPanel extends Pane {
	private final Log log = Log.getLog(getClass());
	
	private String  storeId;
	private Cabinet  cabinet;
	private SerialCommunication serialCommunication;
	private List<StoreBox> storeBoxs;
	private Label archiveTotalValue;
	private Label archiveOpenValue;
	private Label archiveErrorValue;
	private ImageView iconImageView;
	private Label messageLabel;
	private CabinetPanel me;
	
	public CabinetPanel(final CabGroupController controller,final Cabinet cabinet) {
		me=this;
		double usedNum=Db.queryDouble("select count(id) from "+StoreBox.TABLE_NAME+" where cabinetId=?",cabinet.getId());
		double faultNum=Db.queryDouble("select count(id) from "+FaultBox.TABLE_NAME+" where cabinetId=?",cabinet.getId());
		this.storeId=controller.storeId.get();
		this.cabinet=cabinet;
		
		this.setPrefSize(288.0, 460);
		this.setMaxSize(288.0, 460);
		this.setMinSize(288.0, 460);
		this.setId("group-card");
		
		Label label=new Label();
		label.setLayoutX(0);
		label.setLayoutY(37.0);
		label.setPrefSize(287.0, 72.0);
		label.setMaxSize(287.0, 72.0);
		label.setMinSize(287.0, 72.0);
		label.setId("group-card-header");
		label.setText(cabinet.getName());
		
		ImageView faultIcon = new ImageView();
		faultIcon.setImage(new Image(getClass().getResourceAsStream("/application/resources/icon-Fault.png")));
		faultIcon.setX(52.75);
		faultIcon.setY(151.5);
		faultIcon.setFitHeight(18.0);
		faultIcon.setFitWidth(20.0);

		ImageView vacantIcon = new ImageView();
		vacantIcon.setImage(new Image(getClass().getResourceAsStream("/application/resources/icon-Vacant.png")));
		vacantIcon.setX(52.75);
		vacantIcon.setY(188.5);
		vacantIcon.setFitHeight(18.0);
		vacantIcon.setFitWidth(20.0);
		
		ImageView useIcon = new ImageView();
		useIcon.setImage(new Image(getClass().getResourceAsStream("/application/resources/icon-uses.png")));
		useIcon.setX(52.75);
		useIcon.setY(224.5);
		useIcon.setFitHeight(18.0);
		useIcon.setFitWidth(20.0);
		
		
		Label freeLabel=new Label();
		freeLabel.setLayoutX(86.0);
		freeLabel.setLayoutY(148.0);
		freeLabel.setId("group-label");
		freeLabel.setText("空闲数量:");
		
		Label useLabel=new Label();
		useLabel.setLayoutX(86.0);
		useLabel.setLayoutY(182.0);
		useLabel.setId("group-label");
		useLabel.setText("使用数量:");
		
		Label faultLabel=new Label();
		faultLabel.setLayoutX(86.0);
		faultLabel.setLayoutY(218.0);
		faultLabel.setId("group-label");
		faultLabel.setText("故障数量:");
		
		
		Label freeValue=new Label();
		freeValue.setLayoutX(183.0);
		freeValue.setLayoutY(148.0);
		freeValue.setId("group-label");
		freeValue.setText((cabinet.getTotal()-faultNum-usedNum)+"");
		
		Label useValue=new Label();
		useValue.setLayoutX(183.0);
		useValue.setLayoutY(183.0);
		useValue.setId("group-label");
		useValue.setText(usedNum+"");
		
		Label faultValue=new Label();
		faultValue.setLayoutX(183.0);
		faultValue.setLayoutY(220.0);
		faultValue.setId("group-label");
		faultValue.setText(faultNum+"");
		
		
		this.getChildren().add(label);
		this.getChildren().add(faultIcon);
		this.getChildren().add(vacantIcon);
		this.getChildren().add(useIcon);
		this.getChildren().add(freeLabel);
		this.getChildren().add(useLabel);
		this.getChildren().add(faultLabel);
		this.getChildren().add(freeValue);
		this.getChildren().add(useValue);
		this.getChildren().add(faultValue);
		
		if(!controller.open.get()) {
			this.setOnMouseClicked(new EventHandler<MouseEvent>() {
				public void handle(MouseEvent event) {
					if(!controller.isDestroy()) {
						controller.setDestroy(true);
						me.setOnMouseClicked(null);
						ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
							@Override
							protected Void call() throws Exception {
								controller.destroy();
								RouteUtil.goCabinet(controller.storeId.get(),cabinet);
								return null;
							}
						},"前往【"+cabinet.getName()+"】中...").show();
					}
				}
			});
		}else {
			iconImageView = new ImageView();
			iconImageView.setImage(new Image(getClass().getResourceAsStream("/application/resources/fine.png")));
			iconImageView.setX(241);
			iconImageView.setY(0);
			iconImageView.setFitHeight(38);
			iconImageView.setFitWidth(47);
			iconImageView.setVisible(false);
			this.getChildren().add(iconImageView);
			
			storeBoxs=StoreBox.dao.find("select * from "+StoreBox.TABLE_NAME+" where cabinetId=? and storeId=?",cabinet.getId(),storeId);
			ImageView archiveTotalIcon = new ImageView();
			archiveTotalIcon.setImage(new Image(getClass().getResourceAsStream("/application/resources/box.png")));
			archiveTotalIcon.setX(52.75);
			archiveTotalIcon.setY(251);
			archiveTotalIcon.setFitHeight(23.0);
			archiveTotalIcon.setFitWidth(23.0);
			
			ImageView archiveOpenIcon = new ImageView();
			archiveOpenIcon.setImage(new Image(getClass().getResourceAsStream("/application/resources/box-open.png")));
			archiveOpenIcon.setX(52.75);
			archiveOpenIcon.setY(281);
			archiveOpenIcon.setFitHeight(23);
			archiveOpenIcon.setFitWidth(23.0);
			
			ImageView archiveErrorIcon = new ImageView();
			archiveErrorIcon.setImage(new Image(getClass().getResourceAsStream("/application/resources/box-error.png")));
			archiveErrorIcon.setX(52.75);
			archiveErrorIcon.setY(311);
			archiveErrorIcon.setFitHeight(23.0);
			archiveErrorIcon.setFitWidth(23.0);
			this.getChildren().add(archiveTotalIcon);
			this.getChildren().add(archiveOpenIcon);
			this.getChildren().add(archiveErrorIcon);
			
			Label archiveTotalLabel=new Label();
			archiveTotalLabel.setLayoutX(86.0);
			archiveTotalLabel.setLayoutY(250.0);
			archiveTotalLabel.setId("group-label");
			archiveTotalLabel.setText("占用数量:");
			
			archiveTotalValue=new Label();
			archiveTotalValue.setLayoutX(183.0);
			archiveTotalValue.setLayoutY(250.0);
			archiveTotalValue.setId("group-label");
			archiveTotalValue.setText((storeBoxs!=null)?storeBoxs.size()+"":"0");
			this.getChildren().add(archiveTotalLabel);
			this.getChildren().add(archiveTotalValue);
			
			Label archiveOpenLabel=new Label();
			archiveOpenLabel.setLayoutX(86.0);
			archiveOpenLabel.setLayoutY(280.0);
			archiveOpenLabel.setId("group-label-succ");
			archiveOpenLabel.setText("开启数量:");
			
			archiveOpenValue=new Label();
			archiveOpenValue.setLayoutX(183.0);
			archiveOpenValue.setLayoutY(280.0);
			archiveOpenValue.setId("group-label-succ");
			archiveOpenValue.setText("0");
			
			this.getChildren().add(archiveOpenLabel);
			this.getChildren().add(archiveOpenValue);
			
			Label archiveErrorLabel=new Label();
			archiveErrorLabel.setLayoutX(86.0);
			archiveErrorLabel.setLayoutY(310.0);
			archiveErrorLabel.setId("group-label-error");
			archiveErrorLabel.setText("未开数量:");
			
			archiveErrorValue=new Label();
			archiveErrorValue.setLayoutX(183.0);
			archiveErrorValue.setLayoutY(310.0);
			archiveErrorValue.setId("group-label-error");
			archiveErrorValue.setText("0");
			
			this.getChildren().add(archiveErrorLabel);
			this.getChildren().add(archiveErrorValue);
			
			
			messageLabel=new Label();
			messageLabel.setLayoutX(20);
			messageLabel.setLayoutY(393);
			messageLabel.setId("group-label-message");
			this.getChildren().add(messageLabel);
			
			initializeSerialPort();
		}
	}
	
	protected void initializeSerialPort() {
		serialCommunication = new SerialCommunication(cabinet, new SerialPortEventListener() {
			public void serialEvent(SerialPortEvent event) {
				try {
					Thread.sleep(30);
				}catch (Exception e) {
				}
				switch (event.getEventType()) {
				case SerialPortEvent.BI:// 通讯中断
				case SerialPortEvent.OE:// 7 溢位（溢出）错误
				case SerialPortEvent.FE:// 9 帧错误
				case SerialPortEvent.PE:// 8 奇偶校验错误
				case SerialPortEvent.CD:// 6 载波检测
				case SerialPortEvent.CTS:// 3 清除待发送数据
				case SerialPortEvent.DSR:// 4 待发送数据准备好了
				case SerialPortEvent.RI: // 5 振铃指示
				case SerialPortEvent.OUTPUT_BUFFER_EMPTY:// 2 输出缓冲区已清空
					break;
				case SerialPortEvent.DATA_AVAILABLE:// 1 串口存在可用数据
					try {
						   int bufflenth = serialCommunication.getInputStream().available();//获得数据长度
						   byte[] bget;
						   while (bufflenth > 0) {
							 bget = new byte[bufflenth];
							 serialCommunication.getInputStream().read(bget);
			                 bufflenth = serialCommunication.getInputStream().available();
			                 onReceive(bget);
				           }
					} catch (IOException e) {
					}
					break;
				}
			}
		});
	}
	
	/**
	 * 开柜
	 */
	private int fault=0;
	private boolean isOpen;
	public CabResult doOpen() {
		CabResult cabResult=new CabResult();
		isOpen = serialCommunication.startComPort();
		if(isOpen) {
			if(storeBoxs==null) {
				log.info(String.format("【%s】未检测到【%s】存储信息，请核实异常！", cabinet.getName(),storeId));
				cabResult.setCode(false);
				cabResult.setMessage(String.format("【%s】未检测到【%s】存储信息，请核实异常！", cabinet.getName(),storeId));
				Platform.runLater(new Runnable() {
					public void run() {
						if(iconImageView!=null) {
							iconImageView.setVisible(true);
							iconImageView.setImage(new Image(getClass().getResourceAsStream("/application/resources/fault.png")));
						}
						if(messageLabel!=null) {
							messageLabel.setText("异常：未检测到存储记录，请核实！");
							messageLabel.setId("group-label-message-warning");
						}
					}
				});
				return cabResult;
			}
			Board board;
			for(StoreBox storeBox:storeBoxs) {
				board=Board.dao.findById(storeBox.getBoardId());
				if(board!=null) {
					currCmd=new Cmd(storeBox.getId(),cabinet.getId(),board.getId(),board.getBoardNo(),"",board.getId()+"_"+storeBox.getBoxNo(),storeBox.getBoxNo(),0);
					if (!sendOpenCMD(currCmd)) {
						fault+=1;
					}else {
						if(currCmd.getStatus()==1) {
							openBoxMap.put(currCmd.getBoxNo(), currCmd);
						}else {
							fault+=1;
						}
					}
				}
			}
			Platform.runLater(new Runnable() {
				public void run() {
					if(archiveOpenValue!=null) {
						archiveOpenValue.setText(openBoxMap.size()+"");
					}
					if(archiveErrorValue!=null) {
						archiveErrorValue.setText(fault+"");
					}
					if(fault==0) {
						if(iconImageView!=null) {
							iconImageView.setVisible(true);
							iconImageView.setImage(new Image(getClass().getResourceAsStream("/application/resources/fine.png")));
						}
					}else {
						if(iconImageView!=null) {
							iconImageView.setVisible(true);
							iconImageView.setImage(new Image(getClass().getResourceAsStream("/application/resources/fault.png")));
						}
						
						if(messageLabel!=null) {
							messageLabel.setText("警告：未能全部开启存储柜子.");
							messageLabel.setId("group-label-message-warning");
						}
					}
				}
			});
			
			log.info(String.format("【%s】开启【%s】存储柜子，成功【%s】，失败【%s】.", cabinet.getName(),storeId,openBoxMap.size(),fault));
			cabResult.setCode(true);
			cabResult.setMessage(String.format("【%s】开启【%s】存储柜子，成功【%s】，失败【%s】.", cabinet.getName(),storeId,openBoxMap.size(),fault));
			return cabResult;
		}else {
			log.info(String.format("【%s】开启串口异常，请检查配置或者是否正确接入！", cabinet.getName()));
			cabResult.setCode(false);
			cabResult.setMessage(String.format("【%s】异常，请检查连接是否正常！", cabinet.getName()));
			Platform.runLater(new Runnable() {
				public void run() {
					if(iconImageView!=null) {
						iconImageView.setVisible(true);
						iconImageView.setImage(new Image(getClass().getResourceAsStream("/application/resources/fault.png")));
					}
					if(messageLabel!=null) {
						messageLabel.setText("异常：通讯失败，请联系管理员检修！");
						messageLabel.setId("group-label-message-error");
					}
				}
			});
			return cabResult;
		}
	}
	
	public void close() {
		if(serialCommunication!=null) {
			serialCommunication.release();
		}
	}
	
	private void onReceive(byte[] bget) {
		if (bget != null) {
			if (bget[2] == 0x01) {
				cmdOK = true;
			}
			if (bget[2] == 0x02) {
				cmdOK = true;
				String s1 = Convert.ToString( bget[5], 2);
				String s2 = Convert.ToString( bget[4], 2);
				String s3 = Convert.ToString( bget[3], 2);
				log.info("开关状态(右数)" + (s3 + s2 + s1));
				char[] boxs = Convert.reverse(s3 + s2 + s1);
				
				if(0==currCmd.getModel()) {
					if ('0' == boxs[currCmd.getRealNo()-1]) {
						currCmd.setStatus(1);
					} else {
						currCmd.setStatus(0);
					}
				}
				
				if(1==currCmd.getModel()) {
					if ('1' == boxs[currCmd.getRealNo()-1]) {
						currCmd.setStatus(1);
					} else {
						currCmd.setStatus(0);
					}
				}
			}
			if (bget[2] == 0x3) {
				cmdOK = true;
				String s1 = Convert.ToString( bget[5], 2);
				String s2 = Convert.ToString( bget[4], 2);
				String s3 = Convert.ToString( bget[3], 2);
				log.info("存储状态(右数)" + (s3 + s2 + s1));
				char[] boxs = Convert.reverse(s3 + s2 + s1);
				if ('0' == boxs[currCmd.getRealNo()-1]) {
					currCmd.setStatus(1);
				} else {
					currCmd.setStatus(0);
				}
			}
		}
	}
	
	private boolean isTimeout() {
        long startTime = System.currentTimeMillis();
        while (!cmdOK){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
            }
            long endTime = System.currentTimeMillis();
            if ((endTime-startTime)/1000.0>ShiroUtil.getCabinetTimeout()){
                return true;
            }
        }
		return false;
	}
	
	private Map<String, Cmd> openBoxMap = new HashMap<String, Cmd>();
	private Cmd currCmd;
	private boolean cmdOK;
	private boolean sendOpenCMD(Cmd cmd) {
		if (serialCommunication != null) {
			cmdOK = false;
			boolean isSucc = serialCommunication.sendCMD(CmdUtil.getOpen(cmd.getRealNo(), cmd.getBoardNo()));
			if (isSucc) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
				}
				if(!isTimeout()) {
					log.info("发送开启状态检测命令！");
					cmdOK = false;
					cmd.setModel(0);
					isSucc = serialCommunication.sendCMD(CmdUtil.getOpenStatus(cmd.getRealNo(), cmd.getBoardNo()));
					if (isSucc) {
						log.info("发送开启状态检测命令成功！");
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
						}
						if(!isTimeout()) {
							log.info("发送开启状态检测命令成功,cmdOK="+cmdOK);
							return currCmd.getStatus()==1;
						}else {
							log.info("发送开柜指令无响应！");
							return false;
						}
					} else {
						log.info("发送开启状态检测命令失败！");
						return false;
					}
				}else {
					log.info("发送开柜指令无响应！");
					return false;
				}
			} else {
				return isSucc;
			}
		}
		return false;
	}
	
	private Map<String, Cmd> existBoxMap = new HashMap<String, Cmd>();
	private Map<String, Cmd> closeBoxMap = new HashMap<String, Cmd>();
	public CabResult doSave() {
		CabResult cabResult=new CabResult();
		try {
			existBoxMap.clear();
			closeBoxMap.clear();
			java.util.Iterator<String> it = openBoxMap.keySet().iterator();
			while (it.hasNext()) {
				String key = it.next();
				sendCloseCMD(openBoxMap.get(key));
			}
			String msg=String.format("【%s】，开启【%s】，关闭【%s】，暂未关闭【%s】，存储【%s】,取走【%s】！！",cabinet.getName(), openBoxMap.size(),closeBoxMap.size(),openBoxMap.size()-closeBoxMap.size(),
					existBoxMap.size(), openBoxMap.size()-existBoxMap.size());
			if(closeBoxMap.size()!=openBoxMap.size()) {
				throw new Exception(String.format("【%s】有未关闭的柜子！", cabinet.getName()));
			}
			
			StoreLog storeLog = new StoreLog();
			storeLog.setId(UuidUtil.getUUID());
			storeLog.setCabinetId(cabinet.getId());
			storeLog.setStoreId(storeId);
			storeLog.setUserId(ShiroUtil.getUser().getId());
			storeLog.setStatus("2");
			
			List<String> removeBoxs=new LinkedList<String>();
			List<StoreBoxLog> storeBoxLogs=new LinkedList<StoreBoxLog>();
			StoreBoxLog storeBoxLog;
			Cmd exisCmd ;
			java.util.Iterator<String>  openIt = openBoxMap.keySet().iterator();
			while (openIt.hasNext()) {
				String key = openIt.next();
				exisCmd = openBoxMap.get(key);
				
				storeBoxLog=new StoreBoxLog();
				storeBoxLog.setId(UuidUtil.getUUID());
				storeBoxLog.setLogId(storeLog.getId());
				storeBoxLog.setCabinetId(cabinet.getId());
				storeBoxLog.setBoardId(exisCmd.getBoardId());
				storeBoxLog.setBoxNo(exisCmd.getRealNo());
				storeBoxLog.setStatus("0");
				storeBoxLog.setStoreId(storeId);
				storeBoxLog.setCreateTime(DateKit.toStr(new Date(System.currentTimeMillis()), "yyyy-MM-dd hh:mm:ss"));
				storeBoxLogs.add(storeBoxLog);
				
				if(!existBoxMap.containsKey(key)) {
					removeBoxs.add(exisCmd.getId());
					storeBoxLog=new StoreBoxLog();
					storeBoxLog.setId(UuidUtil.getUUID());
					storeBoxLog.setLogId(storeLog.getId());
					storeBoxLog.setCabinetId(cabinet.getId());
					storeBoxLog.setBoardId(exisCmd.getBoardId());
					storeBoxLog.setBoxNo(exisCmd.getRealNo());
					storeBoxLog.setStatus("2");
					storeBoxLog.setStoreId(storeId);
					storeBoxLog.setCreateTime(DateKit.toStr(new Date(System.currentTimeMillis()), "yyyy-MM-dd hh:mm:ss"));
					storeBoxLogs.add(storeBoxLog);
				}
			}
			cabResult.setCode(true);
			cabResult.setMessage(msg);
			cabResult.setRemoveBoxs(removeBoxs);
			cabResult.setStoreLog(storeLog);
			cabResult.setStoreBoxLogs(storeBoxLogs);
			log.info(msg);
			
			Platform.runLater(new Runnable() {
				public void run() {
					if(archiveOpenValue!=null) {
						archiveOpenValue.setText((openBoxMap.size()-closeBoxMap.size())+"");
					}
				}
			});
			return cabResult;
		}catch (Exception e) {
			cabResult.setCode(false);
			cabResult.setMessage(e.getMessage());
			log.error("提取卷宗柜子保存异常:",e);
			return cabResult;
		}
	}
	
	private boolean sendCloseCMD(Cmd cmd) {
		if (serialCommunication != null) {
			currCmd = cmd;
			cmdOK = false;
			currCmd.setModel(2);
			currCmd.setStatus(0);
			log.info("发送检测存储状态命令");
			boolean isSucc = serialCommunication.sendCMD(CmdUtil.getSaveStatus(currCmd.getRealNo(), currCmd.getBoardNo()));
			if (isSucc) {
				log.info("发送检测存储状态命令成功");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
				}
				if(!isTimeout()) {
					log.info("发送检测存储状态命令响应="+currCmd.getBoxNo());
					if(1==currCmd.getStatus()) {
						if(!existBoxMap.containsKey(currCmd.getBoxNo())) {
							existBoxMap.put(currCmd.getBoxNo(),currCmd);
						}
					}
					log.info("发送关闭检测命令");
					cmdOK = false;
					currCmd.setModel(1);
					currCmd.setStatus(0);
					isSucc = serialCommunication.sendCMD(CmdUtil.getOpenStatus(currCmd.getRealNo(), currCmd.getBoardNo()));
					if (isSucc) {
						log.info("发送关闭检测命令成功");
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
						}
						if (!isTimeout()) {
							log.info("发送关闭检测命令响应="+currCmd.getStatus());
							if(1==currCmd.getStatus()) {
								if(!closeBoxMap.containsKey(currCmd.getBoxNo())) {
									closeBoxMap.put(currCmd.getBoxNo(),currCmd);
								}
							}
							return 1==currCmd.getStatus();
						} else {
							log.info("发送关闭检测命令无响应");
							return false;
						}
					} else {
						return false;
					}
				}else {
					log.info("发送检测存储状态命令无响应");
					return false;
				}
			} else {
				return isSucc;
			}
		}
		return false;
	}

	public boolean isOpen() {
		return isOpen;
	}
	
}
class CabResult{
	private boolean code;
	private String message;
	private List<String> removeBoxs;
	private StoreLog storeLog;
	private List<StoreBoxLog> storeBoxLogs;
	
	public boolean isCode() {
		return code;
	}
	public void setCode(boolean code) {
		this.code = code;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	public List<String> getRemoveBoxs() {
		return removeBoxs;
	}
	public void setRemoveBoxs(List<String> removeBoxs) {
		this.removeBoxs = removeBoxs;
	}
	public StoreLog getStoreLog() {
		return storeLog;
	}
	public void setStoreLog(StoreLog storeLog) {
		this.storeLog = storeLog;
	}
	public List<StoreBoxLog> getStoreBoxLogs() {
		return storeBoxLogs;
	}
	public void setStoreBoxLogs(List<StoreBoxLog> storeBoxLogs) {
		this.storeBoxLogs = storeBoxLogs;
	} 
}
